/**
 * 
 */
package denaris.core.controller;

import javax.microedition.lcdui.game.Sprite;

import denaris.midlet.DenarisGameCanvas.DisplayProperties;

/**
 * <p>
 * This is the base class for all controllers. Controllers manipulate
 * <code>Controllable</code>s. There can be very different types (subclasses)
 * of controllers. KeyboardControllers for instance can be used to steer an
 * entity group via the Devices keys. SplineControllers are used to move an
 * entity group along a spline path. Controllers also control the paths of
 * Particles and Bullets.
 * </p>
 * 
 * @author stkl23
 * 
 */
public abstract class AbstractController {
	public static int SCOPE_X = 0;

	public static int SCOPE_Y = 1;

	public static int SCOPE_WIDTH = 2;

	public static int SCOPE_Y2 = 3;

	/** the object we operate on */
	protected Sprite controllable;

	/** our valid screen scope */
	protected int[] scope = new int[4];

	/** a possible frame sequence */
	protected int[] frameSequence;

	/** the index within the current frame sequence */
	protected int frameIndex = 0;

	public AbstractController() {
		// pre-initialize scope
		scope[SCOPE_X] = 0;
		scope[SCOPE_Y] = DisplayProperties.GAME_TOP;
		scope[SCOPE_WIDTH] = DisplayProperties.DISPLAY_WIDTH;
		scope[SCOPE_Y2] = DisplayProperties.GAME_HEIGHT + DisplayProperties.GAME_TOP;
	}

	/**
	 * Advances the AbstractEntity on step depending on the given
	 * <code>ControllerInput</code>.
	 * 
	 * @return true if the entity could be moved, false if it left scope
	 */
	public abstract boolean advance();

	public void setSprite(Sprite sprite) {
		controllable = sprite;
	}

	public Sprite getSprite() {
		return controllable;
	}

	/**
	 * Deactivates the controller by setting its Sprite to invisible. The sprite
	 * then becomes available in the Controller Sprite Cache.
	 */
	public void deactivate() {
		controllable.setVisible(false);
	}

	protected boolean isInScope(int x, int y) {
		return x >= scope[SCOPE_X] && x < scope[SCOPE_WIDTH]
				&& y >= scope[SCOPE_Y] && y < scope[SCOPE_Y2];
	}

	/**
	 * Override this method to reset the controller. Resetting is necessary when
	 * the controller is being reused.
	 */
	public void reset() {
	}
	
	public void move(int dx, int dy) {
		controllable.move(dx, dy);
	}
}